<?php

namespace App\Service\OpenShop\Merchant;

use App\Enums\OpenShop\Merchant\CacheEnum;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\Rms\RmsShopApi;
use App\Remote\Rms\RmsUserRemote;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Illuminate\Support\Facades\Redis;

class MerchantAuth
{
    /**
     * 商家App的用户信息
     * @param $jwtToken
     * @param $shopId
     * @param $brandId
     * @return array|null
     */
    public static function userInfo($jwtToken, $shopId, $brandId): ?array
    {
        $cacheKey = CacheEnum::jwtCacheKey($jwtToken);
        $data     = Cache::get($cacheKey);
        if (null === $data) {
            $data = Http::withHeaders([
                'Authorization' => $jwtToken,
                'brandId'       => $brandId,
                'shopId'        => $shopId,
            ])->get(config('rms.domain') . 'api/merchant/user')
                        ->json('data');

            if (isset($data['id'])) {
                Cache::put($cacheKey, $data, now()->addSeconds(5));
            } else {
                $data = null;
            }
        }

        return $data;
    }

    public static function userInfoShopLists($jwtToken, $shopId, $brandId)
    {
        $cacheKey = CacheEnum::jwtMergeCacheKey($jwtToken);
        $data     = Cache::get($cacheKey);
        if (null === $data) {
            $data = Http::withHeaders([
                'Authorization' => $jwtToken,
                'brandId'       => $brandId,
                'shopId'        => $shopId,
            ])->get(config('rms.domain') . 'api/merchant/user/getUserInfoShopLists')
                        ->json('data');

            if (isset($data['id'])) {
                Cache::put($cacheKey, $data, now()->addMinute());
            } else {
                $data = null;
            }
        }

        return $data;
    }

    /**
     * @return array|mixed|null
     * @throws GuzzleException
     */
    public static function userinfoWithShopAuth($authorization, $brandId, $shopId, $milliseconds = 0)
    {
        // 判断是否命中缓存
        $redisCacheKey = md5('cache' . $authorization . 'brandId:' . $brandId . 'shopId:' . $shopId);
        $data          = Cache::get($redisCacheKey);
        if ($data != null) {
            return $data;
        }

        // 加锁
        $redisSerNxKey  = md5('setNx' . $authorization . 'brandId:' . $brandId . 'shopId:' . $shopId);
        $nowMillisecond = $milliseconds ?: getMillisecondsTimestamp();

        while (!Redis::setnx($redisSerNxKey, $nowMillisecond)) {

            // 最大循环时间是5s 死锁
            if (getMillisecondsTimestamp() - $nowMillisecond > (8 * 1000)) {
                // 删除key并退出
                Redis::del($redisSerNxKey);
                throw new ResponseHttpException(408, null, '网络不稳定，请稍后再试');
            }

            // 存在锁则等待
            usleep(30 * 1000);
            return self::userinfoWithShopAuth($authorization, $brandId, $shopId, $nowMillisecond);
        }

        // 设置缓存
        $data = Cache::remember($redisCacheKey, 60, function () use ($authorization, $brandId, $shopId) {
            return (new RmsShopApi())->getUserinfoWithShopAuth($authorization, $brandId, $shopId)['data'] ?? null;
        });

        Redis::del($redisSerNxKey);

        return $data;
        // return RmsUserRemote::getUserinfoWithAuth();
    }

    /**
     * 商家App的拥有的所有后台权限，权限表中的action字段
     * @param int $rmsUserId
     * @param int $shopId
     * @param $brandId
     * @return array
     */
    public static function permissions(int $rmsUserId, int $shopId, $brandId): array
    {
        $cacheKey    = CacheEnum::permissionCacheKey($rmsUserId, $shopId, $brandId);
        $permissions = Cache::get($cacheKey);
        if (null === $permissions) {
            $permissions = [];
            $data        = Http::withHeaders([
                'internal-key'   => config('rms.internalKey'),
                'internal-token' => config('rms.internalValue'),
            ])->post(config('rms.domain') . 'api/internal/dashboard/permissions', [
                'userId'  => $rmsUserId,
                'brandId' => $brandId,
                'shopId'  => $shopId,
            ])->json('data');
            foreach ((is_array($data) ? $data : []) as $v) {
                foreach ($v['children'] as $vv) {
                    foreach ($vv['children'] as $vvv) {
                        foreach ($vvv['permissionList'] as $vvvv) {
                            $permissions[] = $vvvv['action'];
                        }
                    }
                }
            }
            if (count($permissions)) {
                Cache::put($cacheKey, $permissions, now()->addMinute());
            }
        }
        return $permissions;
    }

    public static function shopList(string $jwtToken, int $shopId, int $brandId): ?array
    {
        $cacheKey = CacheEnum::shopListCacheKey($jwtToken, $shopId, $brandId);
        $shopList = Cache::get($cacheKey);
        if (null === $shopList) {
            $shopList = Http::withHeaders([
                'authorization' => $jwtToken,
                'brandId'       => $brandId,
                'shopId'        => $shopId,
            ])->get(config('rms.domain') . 'api/merchant/shop/getShopList')
                            ->json('data.lists');
            if (count($shopList)) {
                Cache::put($cacheKey, $shopList, now()->addMinute());
            }
        }
        return $shopList;
    }
}
